{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "feature_columns.ipynb",
      "version": "0.3.2",
      "provenance": [],
      "private_outputs": true,
      "collapsed_sections": [],
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "rNdWfPXCjTjY"
      },
      "source": [
        "##### Copyright 2019 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "cellView": "form",
        "colab_type": "code",
        "id": "I1dUQ0GejU8N",
        "colab": {}
      },
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "c05P9g5WjizZ"
      },
      "source": [
        "# Классифицируй структурированные данные"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "zofH_gCzgplN"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://www.tensorflow.org/tutorials/structured_data/feature_columns\">\n",
        "    <img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" />\n",
        "    View on TensorFlow.org</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs/blob/master/site/ru/tutorials/structured_data/feature_columns.ipynb\">\n",
        "    <img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />\n",
        "    Run in Google Colab</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs/blob/master/site/ru/tutorials/structured_data/feature_columns.ipynb\">\n",
        "    <img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />\n",
        "    View source on GitHub</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a href=\"https://storage.googleapis.com/tensorflow_docs/docs/site/ru/tutorials/structured_data/feature_columns.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\" />Download notebook</a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9YD0qEZdzDeN",
        "colab_type": "text"
      },
      "source": [
        "Note: Вся информация в этом разделе переведена с помощью русскоговорящего Tensorflow сообщества на общественных началах. Поскольку этот перевод не является официальным, мы не гарантируем что он на 100% аккуратен и соответствует [официальной документации на английском языке](https://www.tensorflow.org/?hl=en). Если у вас есть предложение как исправить этот перевод, мы будем очень рады увидеть pull request в [tensorflow/docs](https://github.com/tensorflow/docs) репозиторий GitHub. Если вы хотите помочь сделать документацию по Tensorflow лучше (сделать сам перевод или проверить перевод подготовленный кем-то другим), напишите нам на [docs-ru@tensorflow.org list](https://groups.google.com/a/tensorflow.org/forum/#!forum/docs-ru)."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "K1y4OHpGgss7"
      },
      "source": [
        "Этот учебник показывает, как классифицировать структурированные данные (например, табличные данные в CSV). Мы будем использовать [Keras](https://www.tensorflow.org/guide/keras) чтобы определить модель и [feature columns](https://www.tensorflow.org/guide/feature_columns) в для отображения столбцов в CSV в признаки, используемыми для обучения модели. Этот учебник содержит полный код с помощью которого Вы сможете:\n",
        "\n",
        "* Загрузить CSV файл с использованием [Pandas](https://pandas.pydata.org/).\n",
        "* Создать входной пайплайн для пакетной обработки и перемешивания строк, используя [tf.data](https://www.tensorflow.org/guide/datasets).\n",
        "* Отобразить колонки CSV в признаки используемые для обучения модели используя feature columns.\n",
        "* Построить, обучить и оценить модель используя Keras.\n",
        "\n",
        "## Набор данных\n",
        "\n",
        "Мы будем использовать небольшой [датасет](https://archive.ics.uci.edu/ml/datasets/heart+Disease) предоставленный Кливлендской клиникой (Cleveland Clinic Foundation for Heart Disease). Датасет содержит несколько сотен строк в формате CSV. Каждая строка описывает пациента, а каждая колонка характеризует свойство. Мы будем использовать эту информацию чтобы предсказать, есть ли у пациента сердечное заболевание, что в этом наборе данных является задачей бинарной классификации.\n",
        "\n",
        "По ссылке [описание](https://archive.ics.uci.edu/ml/machine-learning-databases/heart-disease/heart-disease.names) этого датасета. Обратите внимание что в нем есть и числовые и категорийные столбцы.\n",
        "\n",
        ">Column| Description| Feature Type | Data Type\n",
        ">------------|--------------------|----------------------|-----------------\n",
        ">Age | Age in years | Numerical | integer\n",
        ">Sex | (1 = male; 0 = female) | Categorical | integer\n",
        ">CP | Chest pain type (0, 1, 2, 3, 4) | Categorical | integer\n",
        ">Trestbpd | Resting blood pressure (in mm Hg on admission to the hospital) | Numerical | integer\n",
        ">Chol | Serum cholestoral in mg/dl | Numerical | integer\n",
        ">FBS | (fasting blood sugar > 120 mg/dl) (1 = true; 0 = false) | Categorical | integer\n",
        ">RestECG | Resting electrocardiographic results (0, 1, 2) | Categorical | integer\n",
        ">Thalach | Maximum heart rate achieved | Numerical | integer\n",
        ">Exang | Exercise induced angina (1 = yes; 0 = no) | Categorical | integer\n",
        ">Oldpeak | ST depression induced by exercise relative to rest | Numerical | integer\n",
        ">Slope | The slope of the peak exercise ST segment | Numerical | float\n",
        ">CA | Number of major vessels (0-3) colored by flourosopy | Numerical | integer\n",
        ">Thal | 3 = normal; 6 = fixed defect; 7 = reversable defect | Categorical | string\n",
        ">Target | Diagnosis of heart disease (1 = true; 0 = false) | Classification | integer"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "VxyBFc_kKazA"
      },
      "source": [
        "## Импортируйте TensorFlow и прочие библиотеки"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "LuOWVJBz8a6G",
        "colab": {}
      },
      "source": [
        "!pip install sklearn"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "9dEreb4QKizj",
        "colab": {}
      },
      "source": [
        "from __future__ import absolute_import, division, print_function, unicode_literals\n",
        "\n",
        "import numpy as np\n",
        "import pandas as pd\n",
        "\n",
        "try:\n",
        "  # Colab only\n",
        "  %tensorflow_version 2.x\n",
        "except Exception:\n",
        "    pass\n",
        "import tensorflow as tf\n",
        "\n",
        "from tensorflow import feature_column\n",
        "from tensorflow.keras import layers\n",
        "from sklearn.model_selection import train_test_split"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "KCEhSZcULZ9n"
      },
      "source": [
        "## Используйте Pandas чтобы создать датафрейм\n",
        "\n",
        "[Pandas](https://pandas.pydata.org/) это библиотека Python множеством полезных утилит для загрузки и работы со структурированными данными. Мы будем использовать Pandas для скачивания данных по ссылке и выгрузки их в датафрейм."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "REZ57BXCLdfG",
        "colab": {}
      },
      "source": [
        "URL = 'https://storage.googleapis.com/applied-dl/heart.csv'\n",
        "dataframe = pd.read_csv(URL)\n",
        "dataframe.head()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "u0zhLtQqMPem"
      },
      "source": [
        "## Разбейте датафрейм на обучающую, проверочную и тестовую выборки\n",
        "\n",
        "Датасет который мы скачали был одним CSV файлом. Мы разделим его на тренировочную, проверочную и тестовую выборки."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "YEOpw7LhMYsI",
        "colab": {}
      },
      "source": [
        "train, test = train_test_split(dataframe, test_size=0.2)\n",
        "train, val = train_test_split(train, test_size=0.2)\n",
        "print(len(train), 'train examples')\n",
        "print(len(val), 'validation examples')\n",
        "print(len(test), 'test examples')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "84ef46LXMfvu"
      },
      "source": [
        "## Создайте входной пайплайн с помощью tf.data\n",
        "\n",
        "Далее мы обернем датафреймы в [tf.data](https://www.tensorflow.org/guide/datasets). Это позволит нам использовать feature columns в качестве моста для отображения столбцов датафрейма Pandas в признаки используемые для обучения модели. Если бы мы работали с очень большим CSV файлом (таким большим, что он не помещается в память), нам нужно было использовать tf.data чтобы прочитать его напрямую с диска. Подобный случай не рассматривается в этом уроке."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "NkcaMYP-MsRe",
        "colab": {}
      },
      "source": [
        "# Вспомогательный метод для создания tf.data dataset из датафрейма Pandas\n",
        "def df_to_dataset(dataframe, shuffle=True, batch_size=32):\n",
        "  dataframe = dataframe.copy()\n",
        "  labels = dataframe.pop('target')\n",
        "  ds = tf.data.Dataset.from_tensor_slices((dict(dataframe), labels))\n",
        "  if shuffle:\n",
        "    ds = ds.shuffle(buffer_size=len(dataframe))\n",
        "  ds = ds.batch(batch_size)\n",
        "  return ds"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "CXbbXkJvMy34",
        "colab": {}
      },
      "source": [
        "batch_size = 5 # Небольшой размер пакета используется для демонстрационных целей\n",
        "train_ds = df_to_dataset(train, batch_size=batch_size)\n",
        "val_ds = df_to_dataset(val, shuffle=False, batch_size=batch_size)\n",
        "test_ds = df_to_dataset(test, shuffle=False, batch_size=batch_size)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "qRLGSMDzM-dl"
      },
      "source": [
        "## Поймите входной пайплайн\n",
        "\n",
        "Сейчас когда мы создали входной пайплайн, давайте вызовем его чтобы увидеть формат данных который он возвращает. Мы использовали небольшой размер пакета чтобы результат был читабельный."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "CSBo3dUVNFc9",
        "colab": {}
      },
      "source": [
        "for feature_batch, label_batch in train_ds.take(1):\n",
        "  print('Every feature:', list(feature_batch.keys()))\n",
        "  print('A batch of ages:', feature_batch['age'])\n",
        "  print('A batch of targets:', label_batch )"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "OT5N6Se-NQsC"
      },
      "source": [
        "Мы видим что датасет возвращает словарь имен столбцов (из датафрейма) который сопоставляет их значениям столбцов взятых из строк датафрейма."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "ttIvgLRaNoOQ"
      },
      "source": [
        "## Продемонстрируем несколько видов столбцов признаков (feature columns)\n",
        "TensorFlow предоставляет множество типов столбцов признаков. В этом разделе мы создадим несколько видов столбцов признаков и покажем как они преобразуют столбцы из датафрейма."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "mxwiHFHuNhmf",
        "colab": {}
      },
      "source": [
        "# Мы используем этот пакте для демонстрации нескольких видов столбцов признаков\n",
        "example_batch = next(iter(train_ds))[0]"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "0wfLB8Q3N3UH",
        "colab": {}
      },
      "source": [
        "# Служебный метод для создания столбца признаков\n",
        "# и преобразования пакета данных\n",
        "def demo(feature_column):\n",
        "  feature_layer = layers.DenseFeatures(feature_column)\n",
        "  print(feature_layer(example_batch).numpy())"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "Q7OEKe82N-Qb"
      },
      "source": [
        "### Численные столбцы (numeric columns)\n",
        "Выходные данные столбцов признаков становятся входными данными модели (используя демо функцию определенную выше мы сможем посмотреть как конкретно преобразуется каждый столбец датафрейма). Числовой столбец [(numeric column)](https://www.tensorflow.org/api_docs/python/tf/feature_column/numeric_column) простейший вид столбца. Он используется для представления числовых признаков. При использовании этого столбца модель получает столбец значений из датафрейма без изменений."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "QZTZ0HnHOCxC",
        "colab": {}
      },
      "source": [
        "age = feature_column.numeric_column(\"age\")\n",
        "demo(age)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "7a6ddSyzOKpq"
      },
      "source": [
        "В наборе данных о сердечных заболеваниях большинство столбцов из датафрейма - числовые."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "IcSxUoYgOlA1"
      },
      "source": [
        "### Сгруппированные столбцы (bucketized columns)\n",
        "Часто вы не хотите передавать числа непосредственно в модель, а вместо этого делите их на несколько категорий на основе числовых диапазонов. Рассмотрим данные представляющие возраст человека. Вместо представления возраста как числового столбца мы можем разбить возраст на несколько категорий использовав [сгруппированный столбец](https://www.tensorflow.org/api_docs/python/tf/feature_column/bucketized_column). Обратите внимание, что one-hot значения приведенные ниже описывают к которому возрастному диапазону относится каждая из строк."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "wJ4Wt3SAOpTQ",
        "colab": {}
      },
      "source": [
        "age_buckets = feature_column.bucketized_column(age, boundaries=[18, 25, 30, 35, 40, 45, 50, 55, 60, 65])\n",
        "demo(age_buckets)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "r1tArzewPb-b"
      },
      "source": [
        "### Категориальные столбцы (categorical columns)\n",
        "В этом датасете thal представлен в виде строк (например 'fixed', 'normal', или 'reversible'). Мы не можем передать строки напрямую в модель. Вместо этого мы должны сперва поставить им в соответствие численные значения. Словарь категориальных столбцов (categorical vocabulary columns) обеспечивает способ представления строк в виде one-hot векторов (как вы видели выше для возраста разбитого на категории). Справочник может быть передан как список с использованием [categorical_column_with_vocabulary_list](https://www.tensorflow.org/api_docs/python/tf/feature_column/categorical_column_with_vocabulary_list), или загружен из файла с использованием [categorical_column_with_vocabulary_file](https://www.tensorflow.org/api_docs/python/tf/feature_column/categorical_column_with_vocabulary_file)."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "DJ6QnSHkPtOC",
        "colab": {}
      },
      "source": [
        "thal = feature_column.categorical_column_with_vocabulary_list(\n",
        "      'thal', ['fixed', 'normal', 'reversible'])\n",
        "\n",
        "thal_one_hot = feature_column.indicator_column(thal)\n",
        "demo(thal_one_hot)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "dxQloQ9jOoXL"
      },
      "source": [
        "В более сложных датасетах многие столбцы бывают категориальными (т.е. строками). Столбцы признаков наиболее полезны при работе с категориальными данными. Хотя в этом наборе данных есть только один категориальный столбец, мы будем использовать его для демонстрации нескольких важных видов столбцов признаков, которые вы можете использовать при работе с другими наборами данных."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "LEFPjUr6QmwS"
      },
      "source": [
        "### Столбцы векторных представлений (embedding column)\n",
        "Предположим, что вместо нескольких возможных строковых значений мы имеем тысячи и более значений для категорий. По ряду причин когда число категорий сильно вырастает, становится невозможным обучение нейронной сети с использованием one-hot кодирования. Мы можем использовать столбец векторных представлений для преодоления этого ограничения. Вместо представления данных в виде многомерных one-hot векторов [столбец векторных представлений](https://www.tensorflow.org/api_docs/python/tf/feature_column/embedding_column) представляет эти данные в виде плотных векторов меньшей размерности, в которых в каждой ячейке может содержаться любое число, а не только О или 1. Размерность векторного представления (8, в нижеприведенном при мере) это параметр который необходимо настраивать.\n",
        "\n",
        "Ключевой момент: использование столбца векторных представлений лучше всего, когда у категориального столбца много возможных значений. Здесь мы используем его только для демонстрационных целей, чтобы у вас был полный пример, который вы можете использовать в будущем для другого набора данных."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "hSlohmr2Q_UU",
        "colab": {}
      },
      "source": [
        "# Обратите внимание, что входными данными для столбца векторных представлений является категориальный столбец\n",
        "# который мы создали до этого\n",
        "thal_embedding = feature_column.embedding_column(thal, dimension=8)\n",
        "demo(thal_embedding)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "urFCAvTVRMpB"
      },
      "source": [
        "### Хэшированные столбцы признаков\n",
        "\n",
        "Другим способом представления категориального столбца с большим количеством значений является использование [categorical_column_with_hash_bucket](https://www.tensorflow.org/api_docs/python/tf/feature_column/categorical_column_with_hash_bucket). This feature column calculates a hash value of the input, then selects one of the `hash_bucket_size` buckets to encode a string. When using this column, you do not need to provide the vocabulary, and you can choose to make the number of hash_buckets significantly smaller than the number of actual categories to save space.\n",
        "\n",
        "Ключевой момент: Важным недостатком этого метода является то, что возможны коллизии, при которых разные строки отображаются в одну и ту же категорию. На практике метод хорошо работает для некоторых наборов данных."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "YHU_Aj2nRRDC",
        "colab": {}
      },
      "source": [
        "thal_hashed = feature_column.categorical_column_with_hash_bucket(\n",
        "      'thal', hash_bucket_size=1000)\n",
        "demo(feature_column.indicator_column(thal_hashed))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "fB94M27DRXtZ"
      },
      "source": [
        "### Пересеченные столбцы признаков (crossed feature columns)\n",
        "Комбинирование признаков в один больше известное как [пересечение признаков](https://developers.google.com/machine-learning/glossary/#feature_cross), позволяет модели изучать отдельные веча для каждой комбинации свойств. Здесь мы создадим новый признак являющийся пересечением возраста и thal. Обратите внимание на то, что `crossed_column` не строит полную таблицу комбинаций значений признаков (которая может быть очень большой). Вместо этого он поддерживает `hashed_column` так что Вы можете сами выбирать размер таблицф."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "oaPVERd9Rep6",
        "colab": {}
      },
      "source": [
        "crossed_feature = feature_column.crossed_column([age_buckets, thal], hash_bucket_size=1000)\n",
        "demo(feature_column.indicator_column(crossed_feature))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "ypkI9zx6Rj1q"
      },
      "source": [
        "## Выберите которые столбцы использовать\n",
        "Мы увидели как использовать несколько видов столбцов признаков. Сейчас мы их используем для обучения модели. Данное руководство покажет Вам полный код (т.е. механизм) необходимый для работы со столбцами признаков. Мы ниже случайно выбрали несколько столбцов для обучения нашей модели.\n",
        "\n",
        "Ключевой момент: если вы собиратесь построить точную модель, попробуйте сами больший набор данных и тщательно подумайте о том, какие признаки являются наиболее значимыми для включения и как они должны быть представлены."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "4PlLY7fORuzA",
        "colab": {}
      },
      "source": [
        "feature_columns = []\n",
        "\n",
        "# численные столбцы\n",
        "for header in ['age', 'trestbps', 'chol', 'thalach', 'oldpeak', 'slope', 'ca']:\n",
        "  feature_columns.append(feature_column.numeric_column(header))\n",
        "\n",
        "# группировка значений столбцов\n",
        "age_buckets = feature_column.bucketized_column(age, boundaries=[18, 25, 30, 35, 40, 45, 50, 55, 60, 65])\n",
        "feature_columns.append(age_buckets)\n",
        "\n",
        "# столбцы индикаторы\n",
        "thal = feature_column.categorical_column_with_vocabulary_list(\n",
        "      'thal', ['fixed', 'normal', 'reversible'])\n",
        "thal_one_hot = feature_column.indicator_column(thal)\n",
        "feature_columns.append(thal_one_hot)\n",
        "\n",
        "# столбцы векторных представлений\n",
        "thal_embedding = feature_column.embedding_column(thal, dimension=8)\n",
        "feature_columns.append(thal_embedding)\n",
        "\n",
        "# столбцы пересечений свойств\n",
        "crossed_feature = feature_column.crossed_column([age_buckets, thal], hash_bucket_size=1000)\n",
        "crossed_feature = feature_column.indicator_column(crossed_feature)\n",
        "feature_columns.append(crossed_feature)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "M-nDp8krS_ts"
      },
      "source": [
        "### Создайте слой признаков\n",
        "Сейчас, после того как мы определили колонки признаков, используем слой [DenseFeatures](https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/keras/layers/DenseFeatures) чтобы передать их в модель Keras."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "6o-El1R2TGQP",
        "colab": {}
      },
      "source": [
        "feature_layer = tf.keras.layers.DenseFeatures(feature_columns)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "8cf6vKfgTH0U"
      },
      "source": [
        "Ранее мы использовали пакеты маленького размера, чтобы показать вам как работают колонки признаков. Сейчас мы создали новый входной пайплайн с большим размером пакетов."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "gcemszoGSse_",
        "colab": {}
      },
      "source": [
        "batch_size = 32\n",
        "train_ds = df_to_dataset(train, batch_size=batch_size)\n",
        "val_ds = df_to_dataset(val, shuffle=False, batch_size=batch_size)\n",
        "test_ds = df_to_dataset(test, shuffle=False, batch_size=batch_size)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "bBx4Xu0eTXWq"
      },
      "source": [
        "## Создайте, скомпилируйте и обучите модель"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "_YJPPb3xTPeZ",
        "colab": {}
      },
      "source": [
        "model = tf.keras.Sequential([\n",
        "  feature_layer,\n",
        "  layers.Dense(128, activation='relu'),\n",
        "  layers.Dense(128, activation='relu'),\n",
        "  layers.Dense(1, activation='sigmoid')\n",
        "])\n",
        "\n",
        "model.compile(optimizer='adam',\n",
        "              loss='binary_crossentropy',\n",
        "              metrics=['accuracy'],\n",
        "              run_eagerly=True)\n",
        "\n",
        "model.fit(train_ds,\n",
        "          validation_data=val_ds,\n",
        "          epochs=5)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "GnFmMOW0Tcaa",
        "colab": {}
      },
      "source": [
        "loss, accuracy = model.evaluate(test_ds)\n",
        "print(\"Accuracy\", accuracy)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "3bdfbq20V6zu"
      },
      "source": [
        "Ключевой момент: вы, как правило, получите лучшие результаты при использовании глубокого обучения с гораздо большими и более сложными датасетами. При работе с небольшими наборами данных, подобным этому, мы рекомендуем использовать дерево решений или случайный лес в качестве надежной базовой модели. Цель этого руководства - не обучить точную модель, а продемонстрировать механику работы со структурированными данными, дать вам код, который можно использовать в качестве старта при работе с вашими собственными наборами данных в будущем."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "SotnhVWuHQCw"
      },
      "source": [
        "## Следующие шаги\n",
        "Лучший способ узнать больше о классификации структурированных данных - попробовать самостоятельно. Мы предлагаем взять другой набор данных и обучить модель его классифицировать с использованием кода, аналогичного приведенному выше. Чтобы повысить точность, тщательно продумайте, какие признаки включить в вашу модель и как они должны быть представлены."
      ]
    }
  ]
}
